package org.example.commonapi.util.oss;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.example.commonapi.config.OssConfig;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class OssService {

    @Resource
    private OssConfig ossConfig;

    /**
     * 阿里云OSS文件上传
     *
     * @param file
     */
    public String upload(MultipartFile file) {

        // 获取相关配置
        String bucketName = ossConfig.getBucketName(); // 存储空间名称
        String endPoint = ossConfig.getEndPoint(); // OSS服务的访问域名
        String accessKeyId = ossConfig.getAccessKeyId(); // 访问密钥ID
        String accessKeySecret = ossConfig.getAccessKeySecret(); // 访问密钥Secret

        // 创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret); // 使用访问域名、访问密钥ID和访问密钥Secret构建OSS客户端对象

        // 生成文件名
        String uploadFileName=createUploadFileName(file);
        System.out.println("上传文件名");
        System.out.println(uploadFileName);

        try {
            PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream()); // 将上传的文件流上传到OSS，并返回上传结果
            System.out.println(result);
            // 拼装返回路径
            if (result != null) {
                log.info("文件上传成功，文件名：{}",uploadFileName); // 如果上传成功，记录日志
                return "https://"+bucketName+"."+endPoint+"/"+uploadFileName; // 如果上传成功，返回文件的访问URL
            }
        } catch (IOException e) {
            log.error("文件上传失败：{}",e.getMessage()); // 如果上传过程中发生异常，记录错误日志
        } finally {
            // OSS关闭服务，不然会造成OOM
            ossClient.shutdown(); // 关闭OSS客户端，释放资源
        }
        return null; // 如果上传失败，返回null
    }

    /**
     * 上传文件列表
     * @param files
     * @return
     */
    public List<String > uploadList(List<MultipartFile> files) {

        // 获取相关配置
        String bucketName = ossConfig.getBucketName(); // 存储空间名称
        String endPoint = ossConfig.getEndPoint(); // OSS服务的访问域名
        String accessKeyId = ossConfig.getAccessKeyId(); // 访问密钥ID
        String accessKeySecret = ossConfig.getAccessKeySecret(); // 访问密钥Secret
        //        创建address数组存地址
        List<String> address=new ArrayList<>();
        // 创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret); // 使用访问域名、访问密钥ID和访问密钥Secret构建OSS客户端对象
        for(MultipartFile file : files){
            String uploadFileName=createUploadFileName(file);
            try {
                PutObjectResult result = ossClient.putObject(bucketName, uploadFileName, file.getInputStream()); // 将上传的文件流上传到OSS，并返回上传结果
                // 拼装返回路径
                if (result != null) {
                    log.info("文件上传成功，文件名：{}",uploadFileName); // 如果上传成功，记录日志
                    address.add("https://"+bucketName+"."+endPoint+"/"+uploadFileName);  // 如果上传成功，返回文件的访问URL
                }
            } catch (IOException e) {
                log.error("文件上传失败：{}",e.getMessage()); // 如果上传过程中发生异常，记录错误日志
            } finally {
                // OSS关闭服务，不然会造成OOM
                ossClient.shutdown(); // 关闭OSS客户端，释放资源
            }
            return null; // 如果上传失败，返回null
        }
        return address;
    }

    public void download(String oosFilePath, String localFilePath) {
        // 获取相关配置
        String bucketName = ossConfig.getBucketName(); // 存储空间名称
        String endPoint = ossConfig.getEndPoint(); // OSS服务的访问域名
        String accessKeyId = ossConfig.getAccessKeyId(); // 访问密钥ID
        String accessKeySecret = ossConfig.getAccessKeySecret(); // 访问密钥Secret
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        ossClient.getObject(new GetObjectRequest(bucketName, oosFilePath), new File(localFilePath));
        ossClient.shutdown();
    }

    /**
     * 获取随机字符串
     * @return
     */
    private String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
    }

    /**
     * 生成上传文件名
     * @param file
     * @return
     */
    private String createUploadFileName(MultipartFile file){
        // 获取原生文件名
        String originalFilename = file.getOriginalFilename(); // 获取上传文件的原始文件名
        // JDK8的日期格式
        LocalDateTime time = LocalDateTime.now(); // 获取当前时间
        DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy/MM/dd"); // 定义日期格式化对象，用于将日期格式化为"yyyy/MM/dd"格式

        // 拼装OSS上存储的路径
        String folder = dft.format(time); // 将当前时间格式化为"yyyy/MM/dd"格式的字符串
        String fileName = generateUUID(); // 生成一个随机的唯一标识符作为文件名
        String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); // 获取上传文件的扩展名

        // 在OSS上bucket下的文件名
        String uploadFileName = "user/" + folder + "/" + fileName + extension; // 拼接上传到OSS的文件名，格式为"user/年/月/日/唯一标识符.扩展名"
        return uploadFileName;
    }
}
